package com.telenav.oauth;

import java.net.URI;
import java.net.URISyntaxException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

import org.apache.amber.oauth2.as.issuer.MD5Generator;
import org.apache.amber.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.amber.oauth2.as.request.OAuthAuthzRequest;
import org.apache.amber.oauth2.as.response.OAuthASResponse;
import org.apache.amber.oauth2.common.OAuth;
import org.apache.amber.oauth2.common.error.OAuthError;
import org.apache.amber.oauth2.common.exception.OAuthProblemException;
import org.apache.amber.oauth2.common.exception.OAuthSystemException;
import org.apache.amber.oauth2.common.message.OAuthResponse;
import org.apache.amber.oauth2.common.message.types.ResponseType;
import org.apache.amber.oauth2.common.utils.OAuthUtils;

/**
 *
 *
 *
 */
@Path("/authz")
public class MyAuthz {

	@GET
	public Response authorize(@Context HttpServletRequest request) throws URISyntaxException, OAuthSystemException {

		OAuthAuthzRequest oauthRequest = null;

		OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());

		try {
			oauthRequest = new OAuthAuthzRequest(request);

			// build response according to response_type
			String responseType = oauthRequest.getResponseType();

			OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND);

			// response_type:REQUIRED;client_id:REQUIRED;redirect_uri:OPTIONAL;scope:OPTIONAL;state:RECOMMENDED
			if (responseType.equals(ResponseType.CODE.toString())) {
				if (!oauthRequest.getScopes().contains("valid_scope")) {
					OAuthProblemException exception = OAuthProblemException.error(OAuthError.CodeResponse.INVALID_SCOPE);
					exception.setRedirectUri(oauthRequest.getRedirectURI());
					throw exception;
				} else if (oauthRequest.getClientId().equals("valid_client_id") && oauthRequest.getRedirectURI().equals("valid_redirect_url")) {
					// code:REQUIRED;state:REQUIRED
					builder.setCode(oauthIssuerImpl.authorizationCode());
					if (oauthRequest.getState() != null && !oauthRequest.getState().equals("")) {
						builder.setParam(OAuth.OAUTH_STATE, oauthRequest.getState());
					}
				} else {
					OAuthProblemException exception = OAuthProblemException.error(OAuthError.CodeResponse.INVALID_REQUEST);
					exception.setRedirectUri(oauthRequest.getRedirectURI());
					throw exception;
				}
			}
			// grant_type:REQUIRED;code:REQUIRED;redirect_uri:REQUIRED;client_id:REQUIRED
			if (responseType.equals(ResponseType.TOKEN.toString())) {
				if (!oauthRequest.getScopes().contains("valid_scope")) {
					OAuthProblemException exception = OAuthProblemException.error(OAuthError.CodeResponse.INVALID_SCOPE);
					exception.setRedirectUri(oauthRequest.getRedirectURI());
					throw exception;
				} else if (oauthRequest.getClientId().equals("valid_client_id") && oauthRequest.getParam(OAuth.OAUTH_CODE).equals("valid_code")
						&& oauthRequest.getRedirectURI().equals("valid_redirect_url")) {
					builder.setAccessToken(oauthIssuerImpl.accessToken());
					builder.setExpiresIn(3600L);
				} else {
					OAuthProblemException exception = OAuthProblemException.error(OAuthError.CodeResponse.INVALID_REQUEST);
					exception.setRedirectUri(oauthRequest.getRedirectURI());
					throw exception;
				}
			}

			String redirectURI = oauthRequest.getRedirectURI();

			final OAuthResponse response = builder.location(redirectURI).buildQueryMessage();
			URI url = new URI(response.getLocationUri());

			return Response.status(response.getResponseStatus()).location(url).build();

		} catch (OAuthProblemException e) {

			final Response.ResponseBuilder responseBuilder = Response.status(HttpServletResponse.SC_FOUND);

			String redirectUri = e.getRedirectUri();

			if (OAuthUtils.isEmpty(redirectUri)) {
				throw new WebApplicationException(responseBuilder.entity("OAuth callback url needs to be provided by client!!!").build());
			}
			final OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND).error(e).location(redirectUri).buildQueryMessage();
			final URI location = new URI(response.getLocationUri());
			return responseBuilder.location(location).build();
		}
	}

}
